package zpack

import (
	"bytes"
	"encoding/binary"
	"errors"
)

//消息
type PackBuffer struct {
	DataLen uint32 //消息的长度
	Id      uint16 //消息的ID
	Code    uint16 //返回码
	Data    []byte //消息的内容
}

//创建一个Message
func NewPackBuffer(id uint16, code uint16, data []byte) *PackBuffer {
	return &PackBuffer{
		DataLen: uint32(len(data)),
		Id:      id,
		Code:    code,
		Data:    data,
	}
}

var (
	MaxPackBufferSize    uint32 = 409600 //最大数据包
	MaxPackBufferHeadLen uint32 = 8      //Id uint16(2字节) +  Code uint16(2字节) +  DataLen uint32(4字节)
)

//封包方法(压缩数据)
func PackBufferPack(msg *PackBuffer) ([]byte, error) {
	//创建一个存放bytes字节的缓冲
	dataBuff := bytes.NewBuffer([]byte{})

	//写dataLen
	if err := binary.Write(dataBuff, binary.LittleEndian, msg.DataLen); err != nil {
		return nil, err
	}

	//写msgID
	if err := binary.Write(dataBuff, binary.LittleEndian, msg.Id); err != nil {
		return nil, err
	}

	//写Code
	if err := binary.Write(dataBuff, binary.LittleEndian, msg.Code); err != nil {
		return nil, err
	}

	//写data数据
	if err := binary.Write(dataBuff, binary.LittleEndian, msg.Data); err != nil {
		return nil, err
	}

	return dataBuff.Bytes(), nil
}

//拆包方法(解压数据)
func PackBufferUnpack(binaryData []byte) (*PackBuffer, error) {
	//创建一个从输入二进制数据的ioReader
	dataBuff := bytes.NewReader(binaryData)

	//只解压head的信息，得到dataLen和msgID
	msg := &PackBuffer{}

	//读dataLen
	if err := binary.Read(dataBuff, binary.LittleEndian, &msg.DataLen); err != nil {
		return nil, err
	}

	//读msgID
	if err := binary.Read(dataBuff, binary.LittleEndian, &msg.Id); err != nil {
		return nil, err
	}

	//读Code
	if err := binary.Read(dataBuff, binary.LittleEndian, &msg.Code); err != nil {
		return nil, err
	}

	//判断dataLen的长度是否超出我们允许的最大包长度
	if msg.DataLen > MaxPackBufferSize {
		return nil, errors.New("too large msg data received")
	}

	//这里只需要把head的数据拆包出来就可以了，然后再通过head的长度，再从conn读取一次数据
	return msg, nil
}
